package com.twinkle.auth.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.twinkle.auth.constant.RedisKeyConstants;
import com.twinkle.auth.enums.ResponseCodeEnum;
import com.twinkle.auth.model.vo.SendVerificationCodeReqVO;
import com.twinkle.auth.service.VerificationCodeService;
import com.twinkle.auth.util.EmailSendUtil;
import com.twinkle.framework.common.exception.BusinessException;
import com.twinkle.framework.common.response.Response;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
@Service
@Slf4j
public class VerificationCodeServiceImpl implements VerificationCodeService {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource(name = "taskExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Resource
    private EmailSendUtil emailSendUtil;


    @Override
    public Response<?> send(SendVerificationCodeReqVO sendVerificationCodeReqVO) {
        // 邮箱
        String email = sendVerificationCodeReqVO.getEmail();

        // 构建验证码 redis key
        String key = RedisKeyConstants.buildVerificationCodeKey(email);

        // 判断是否已发送验证码
        boolean isSent = redisTemplate.hasKey(key);
        if (isSent) {
            throw new BusinessException(ResponseCodeEnum.VERIFICATION_CODE_SEND_FREQUENTLY);
        }

        String verificationCode = RandomUtil.randomNumbers(6);

        threadPoolTaskExecutor.execute(() -> {
            emailSendUtil.send(email, verificationCode);
            log.info("==> 邮箱: {}, 已发送验证码：【{}】", email, verificationCode);
        });
        // 存储验证码到 redis, 并设置过期时间为 5 分钟
        redisTemplate.opsForValue().set(key, verificationCode, 5, TimeUnit.MINUTES);

        return Response.success();
    }

}
